!pr1
18-Digit Arithmetic, Part 10...............Bob Sander-Cederlof

At least one error crept into the PRINT USING program we printed last month.  A line should be inserted to correct the problem:

      3045     JSR PRUS.CLEAR    YES, NEW FIELD

This is what I expect to be the final installment of the DP18 series.  Some of you have been typing in and trying out the various installments, and others buying the source code on the various quarterly disks.  We plan to make the composite DP18 source available at a reasonable price:  all parts will be properly integrated as a set of 12 source files, ready to assemble with the S-C Macro Assembler.  The disk will also include example programs illustrating the various features, the object file of DP18, and a loader program for installing DP18.  The price for all of it, on one diskette, will be $50.

Normal Applesoft INPUT statements can be written in several ways.  An optional quotation can be used for a prompting message; if one is used a semicolon must follow the quotation.  A list of one or more variables follows.

       INPUT variable
       INPUT "quote";variable

In DP18 we implemented the two forms of the INPUT statement shown above, except that only a single variable may be used in each statement.  We also implemented two additional kinds of INPUT statements.  INPUT# statements allow expressions to be entered during execution.  INPUT$ statements allow picture- controlled input.

       INPUT # variable
       INPUT # "quote";variable
       INPUT $ string,variable-list

The INPUT# statement allows you to read expressions and evaluate them during an INPUT operation.  This can greatly simplify entering some numbers.  For example, one-third can be entered as either ".3333333333333333333333" or simply as "1/3".  You can enter values such as SQR(2), 2*PI, and so on.  You can even refer to variables used in the program.  After you have entered the expression and typed RETURN, DP18 calls on Applesoft to tokenize the line, evaluates the expression to a numeric value, and stores the value in the INPUT variable your program specified.

We call the INPUT$ statement "INPUT using".  It is analogous to "PRINT using", or the PRINT$ statement discussed last month.  All characters in the INPUT$ picture are proccessed the same as for PRINT$ until characters defining a numeric or string field are encountered.  Then the magic begins....

For a numeric field, underlines are printed to indicate digit positions.  The cursor is placed after the last underline.  If there is a decimal point in the picture it will be printed.  A plus sign in the picture will also be printed.  All other positions of the field will be printed as underlines.  Once the field has been displayed in this fashion, DP18 will check the current value in the variable corresponding with the field.  If the current value is zero, DP18 merely waits for you to enter digits.  If the current value is non-zero, that value is displayed in the field on the screen, to be used as a default value.

When INPUT$ is waiting for you to enter a numeric value, you can type the RETURN key to accept the default value.  If no default value is displayed and you type the RETURN key, you will be entering a value of zero.  If you begin to type digits, they will enter the field from the right end in "calculator style".  Using backspace will cause the displayed value to be popped to the right, deleting the last digit you typed.  One digit will be deleted each time you type backspace.

If you type a period, enough zeroes will be automatically entered to reach the displayed decimal point.  This makes the digits you typed before the period into an integer.  Then as you continue to type digits they will be appended after the decimal point.  If you type more fractional digits than can be seen in the displayed field, they do become part of the input value; you just cannot see them on the screen.  The value on the screen is rounded up if necessary.

A control-X will erase everything you have typed in the current field and allow you to start over.  A control-C will immediately BREAK, stopping the program.

If you type a backspace when there are no digits remaining in a field, DP18 will attempt to go back to the previous field in the same picture.  This will only work if the screen has not scrolled during the development of the picture, and requires a little bit of planning.  (Isn't that what programming is all about?)

Probably it is time for an example.

      100 &DP: INPUT $ "HV>>'ENTER X:  '###.#/
          'ENTER Y:  '###.#",X(0),Y(0)

Remember how to read pictures from last month's article?  The "H" all by itself sets the horizontal cursor position to 0 (beginning of the line).  Likewise, "V" sets us to the top line.  The ">>" clears from cursor to end of screen.  Therefore the "HV>>" does the same thing as a normal HOME command, but from within a picture.  The string between apostrophes is printed on the screen.  Then "###.#" defines a numeric field, corresponding to the variable X(0).  The "/" causes a carriage return to be displayed, and then "ENTER Y:" and the second field.

During execution you will first see the screen clear and the top line become "ENTER X:  ___._" followed by a flashing cursor.  You can type digits, a sign, a decimal point, backspace, and so on.  When you finally type the RETURN a second line will appear:  "ENTER Y:  ___._".  If you then type a backspace, the cursor will move back to the first line, displaying as a default value whatever you left in that line.

And what about string fields in the INPUT$ command?  Again, underlines will be displayed for each position of the string field.  If the string already is non-null, its current value will be displayed as a default.

The code that follows is, as has been our practice throughout the DP18 series, preceded by some .EQ lines to define routines previously published, or part of the Apple ROMs.  Variable storage is also defined.  In the integrated source all these definitions are only done once, and the whole program is assembled together.

When the main execution loop of DP18 encounters the INPUT token, we land at line 1840.  Lines 1850-1860 get the character following INPUT, and abort with SYNTAX ERROR if that character is a colon or end-of-line token.  Lines 1870-1910 handle INPUT$, by merely loading up zero in the A-register and jumping to PRINT.INPUT (which was listed last month as part of the PRINT USING code).  The zero value will be stored in a flag, indicating to PRINT.INPUT later on that it was called from INPUT$ rather than PRINT$.  When the picture processor encounters a numeric or string field description in the picture either INPUT.NUM or INPUT.STR will be called, rather than PRINT.NUM or PRINT.STR.

Lines 1930-2510 handle the normal INPUT and INPUT# modes.  The character which follows INPUT is stored at INPUT.TYPE, to be checked later.  If that character was "#", line 1960 gets the next character to position properly for scanning optional quote or the variable name.  Lines 1970-2120 process the optional quote.  If it is not there, a "?" prompt is used; it it is there, the string itself is printed.  Lines 2090-2110 make a ";" optional after the quote.  Normal Applesoft INPUT requires a semicolon after the quote, but DP18's INPUT makes it optional.  In fact, you could even get by with a whole bunch of semicolons, if you feel like it....

Lines 2140-2190 read a line of text.  If the first character of the line is a control-C, we abort just like Applesoft.  An empty line returns a zero value, using line 2500-2510.

Lines 2210-2270 set up the input line, which begins at $0200 (WBUF), so that it can be scanned using CHRGET, after pushing current TXTPTR value on the stack.  If the INPUT.TYPE was "#", AS.PARSE and DP.EVALUATE convert the expression down to a value.  If not, FIN converts the number string to a value.  I could have used PARSE and EVALUATE regardless, but it would take a lot more time to convert plain numbers that way.  Lines 2400-2430 restore the old value of TXTPTR, so that we can continue scanning the program.

Lines 2440-2480 scan the input variable name, and store the converted value in that variable.  Then back to DP18's main loop to get the next command!

If we are processing an INPUT$ statement, chances are good that we will input a number.  If so, the picture processor will call on INPUT.NUM at line 2530.  WBUF at this time holds the image of the numeric field description, as amplified from the picture.  Lines 2540-2600 copy it into IBUF, because we are going to clobber the WBUF version everytime we re-display the value being entered.  IBUF is currently assembled as a 256 byte buffer, which is quite extravagant.  Probably this is an area where things could be tightened up, if you need the memory space.

The code beyond line 2530 is hard to follow.  I am reminded of the original Adventure game, and its twisty little passages, little twisty passages, and so on.  I am going to give it a broad brush, and those of you with an intense interest can explore in more detail on your own.

As each digit is typed, it is appended to the numeric value by ACCUMULATE.DIGIT.  Then, after refreshing the picture of the field from IBUF, the value is reconverted to display format and shown on the screen.  It may sound inefficient, but it all works nicely.  Trimming off digits when backspace is typed is done by truncating the DP18 value and then redisplaying.

LAST.FLD is the routine that tries to back up input to a previous field when you type backspace beyond the first digit.  At the beginning of each field, all the necessary parameters are pushed on DP18's stack.  LAST.FLD pops these back to move to a previous field.  Guess what ... I forgot to check for stack overflow in the STACK.IT subroutine.  Should be no problem, however, because only five bytes are stacked for each field, there is room for 24 fields.  Since a picture must necessarily be less than 256 characters (maximum length of an Applesoft string) thereby limiting the number of fields, it is unlikely that you will have more than 24 fields stack up.  If you think it important to have more, you had better increase the size of STACK.

String input is handled in an analogous fashion by INPUT.STR, starting at line 4970.

As I mentioned before, this is my final article on DP18.  But maybe not, if you want more.  Some of you might send improvements, corrections, or whatever, and I might pass them along in these pages.

DP18 works, and works well; we're proud of it.  You can use DP18 in your programs, even those you plan to sell.  Just give us credit where appropriate in your documentation.  Remember, you can get all the source code already typed in and integrated together from us for only $50.
1
